/**
 * @class   wosh::BundleManager
 * @brief   WOSH core service which manages bundles (wosh::Bundle).
 *
 *
 * \image html diagrams/BundleManager.png "wosh::BundleManager UML diagram"
 *
 *
 * \par Initialization:
 * \msc
BundleManager,Kernel;
BundleManager->BundleManager [label="WoshModule::onKernelInitializing()", URL="\ref wosh::WoshModule::onKernelInitializing()"];
|||;
--- [ label=" IF BundleConfigFolder "];
BundleManager=>Kernel [label="WoshKernel::getInstance()->settings().loadConfigurationFolder", URL="\ref wosh::Settings::loadConfigurationFolder()"];
--- [ label=" ENDIF BundleConfigFolder "];
|||;
--- [ label=" IF AutoLoadBundles "];
BundleManager rbox BundleManager [label="doAutoLoadBundles()", URL="\ref wosh::BundleManager::doAutoLoadBundles()"];
--- [ label=" ENDIF AutoLoadBundles "];
|||;
--- [ label=" IF AutoStartBundles "];
BundleManager rbox BundleManager [ label="doAutoStart()", URL="\ref wosh::BundleManager::doAutoStart()"];
--- [ label=" ENDIF AutoStartBundles "];
 * \endmsc
 *
 *

 * @ingroup CoreModules
 ****************************************************************************
 * @version 0.8.151 $Id: BundleManager.h 2488 2010-05-21 01:48:27Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
/*! \page page_core
 * \htmlonly <hr/> \endhtmlonly
 * \section page_core_bundles Bundles
 *
 * [..]
 *
 * A generic service of WOSH is called \b Bundle and implements wosh::Bundle
 * interface. Since most implementation would share a lot of common code, an
 * helper class wosh::BundleGeneric is provided for convenience.
 *
 * wosh::BundleManager core module manages bundles, their (un)loading and 
 * life cycle.
 *
 *
 * 
 * \code
// install Bundle loader (built-in bundles)
core.bundles().installBundleAllocator( new BundleAllocatorStatic() );
 * \endcode
 *
 * \see wosh::BundleManager
 * \see wosh::Bundle
 * \see wosh::BundleGeneric
 *
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

#ifndef __WOSH_Core_BundleManager_H__
 #define __WOSH_Core_BundleManager_H__

 #include <woshDefs.h>
 #include <core/Bundle.h>
 #include <core/BundleLoader.h>
 #include <core/WoshModule.h>
 #include <core/MessageQueue.h>
 #include <core/Containers.h>


namespace wosh {

 #define _BundleManager_NAME							"BundleManager"
 #define _BundleManager_URI								":Bundles"

 #define _BundleManager_KEY_Count						"BundlesCount"
 #define _BundleManager_KEY_AutoLoadBundles				"AutoLoadBundles"
 #define _BundleManager_KEY_AutoStartBundles			"AutoStartBundles"
 #define _BundleManager_KEY_BundleConfigFolder			"BundleConfigFolder"
 #define _BundleManager_KEY_BundleLoadFolder			"BundleLoadFolder"
 #define _BundleManager_KEY_BundleLibFolder				"BundleLibFolder"

 #define _BundleManager_METHOD_LoadBundle				"load"
 #define _BundleManager_METHOD_ListSupportedBundles		"list_supported"

 #define _BundleManager_METHOD_control_bundle			"control_bundle"
 
 #define _BundleManager_ERROR_exec_load					10101
 #define _BundleManager_ERROR_exec_unknown				10102
 #define _BundleManager_ERROR_waitstate					201

class WoshKernel;
class Settings;
class BundleAction;

typedef ListT<wosh::Bundle*> tBundleList;

class BundleManager :	public WoshModule
 {
	WOSH_MODULE(wosh::BundleManager)

	protected:
		BundleManager( const WoshKernel* parent = NULL );

		WRESULT onKernelInitializing();
		WRESULT onKernelInitialized();
		WRESULT onKernelRunning();
		WRESULT onKernelStopping();
		WRESULT onKernelStopped();

		friend class wosh::WoshKernel;

	public:
		virtual ~BundleManager();


	public: // reentrant, 

		WRESULT startBundles();
		WRESULT stopBundles();
		WRESULT unloadBundles();

		//
		WRESULT installBundle( Bundle* bundle, bool startBundle = true, bool applySettings = true, unsigned long timeout = LIMIT_ULONG_MAX );

		WRESULT loadBundle( const std::string& bundle_type, const std::string& bundle_name, bool applySettings );

		// reentrant, register a bundle, pointer is acquired (caller can't use it anymore), state not validated
		WRESULT registerBundle( Bundle* bundle );

//		WRESULT loadBundle( const std::string& bundle_type, const std::string& bundle_name = "" );


	protected:
		WRESULT registerBundle_( Bundle* bundle );
		WRESULT unRegisterBundle( Bundle* bundle );


/////////////////////////////////////////////////////////////////////////

/** @name Public methods (bundles)
 * @{
 ******************************************************************************/
	public:


		WRESULT startBundle( Bundle* bundle, bool recursive_start = false, unsigned long timeout = LIMIT_ULONG_MAX );
		WRESULT stopBundle( Bundle* bundle, bool recursive_stop = false, unsigned long timeout = LIMIT_ULONG_MAX );

//		virtual bool isBundleRunning( const string& bundle_name ) const;

		int isBundleStoppable( Bundle* bundle ) const;


		/**
		 * @brief  create delayed loading/starting action 
		 * @param [in] cfgPath folder; when empty it will load from property..
		 * @return WRET_OK
		 */
		WRESULT doAutoLoadBundles( const std::string& cfgPath = "" );

		WRESULT applySettingsOfBundles( Settings* settings );

		const tBundleList& getBundles() const					{ return this->bundles; }
		tBundleList& getBundles()								{ return this->bundles; }

//@}
/** @name Public static methods, provided for convenience (used by thread-implementations)
 * @{
 ******************************************************************************/
	public:
		static bool waitState( const Bundle* bundle, Bundle::BUNDLE_STATE state, unsigned long timeout = LIMIT_ULONG_MAX );
//@}
/** @name protected methods (internally mapped)
 * @{
 ******************************************************************************/
	protected:
		Response* mmDoListSupportedBundles( const Request* request );

		Response* mmDoLoadBundle( const Message* requestMessage );
		Response* mmDoControlBundle( const Message* requestMessage );

		int isBundleStoppable_( Bundle* bundle ) const;//no mutex

		WRESULT startBundle_( Bundle* bundle, long wait_synch = 20000, bool recursive_start = false );
		WRESULT stopBundle_( Bundle* bundle, long wait_synch = 20000, bool recursive_stop = false );

		Bundle* getBundleByName_( const std::string& bundle_name ) const;//no mutex
		Bundle* getBundleByType_( const std::string& bundle_type ) const;//no mutex

//@}
	protected:
		virtual void bundle_event( Bundle::BUNDLE_STATE event, Bundle* bundle );

		friend class wosh::Bundle;

	private:
		static BundleManager* getInstance();

/** @name Internal vars
 * @{
 ******************************************************************************/
	private:
		tBundleList bundles;
		Mutex stateTransitionMux;

//		MessageQueue msgQueue;

		friend class wosh::BundleLoader;
		friend class wosh::BundleAction;
		friend class wosh::BundleActionLoad;
		friend class wosh::BundleActionStart;
		friend class wosh::BundleActionStop;
		friend class wosh::BundleActionUnLoad;

	public:
		BundleLoader loader;

//@}

}; // class def

/*
class Bundle_StateChanged : public Fact
 {


}; // class def
*/


}; // namespace wosh

#endif //__WOSH_Core_BundleManager_H__
